home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / ARGONET / PD / GRAPHICS / GIF2RPC.SPK / source / s / map8_accurat < prev    next >
Text File  |  1995-12-29  |  5KB  |  142 lines

  1. ; map8_accurate.s
  2. ; MACHINE:     RISC OS
  3. ; LANGUAGE:    OBJASM assembler
  4. ; AUTHOR:      Cy Booker, cy@cheepnis.demon.co.uk
  5. ; LICENSE:     FreeWare, Copyright (c) Cy Booker 1995
  6. ; PURPOSE:     Given an arbitary 48-bit colour, what is the closest 8-bit colour number?
  7. ; HISTORY:     1995.12.29 CJB tidied up comments
  8.  
  9.         GET     OS:Hdr.os
  10.  
  11. ;
  12. ; in middle we have |intensity-difference| <-- 0xffff 
  13. ; so |i|^2 <= 0xffffe0001
  14. ; and so to compensate we will have to shift right by quite a lot!
  15. ;
  16. ; the weights we want are:
  17. ;       Red     * 0.212671 * 358 ~=  76  /512 ~= 0x0.2610 ~= 0x0.26
  18. ;       Green   * 0.715160 * 358 ~= 256  /512 ~= 0x0.8000 ~= 0x0.80
  19. ;       Blue    * 0.072169 * 358 ~=  26  /512 ~= 0x0.0ce6 ~= 0x0.0d
  20. ;
  21. ; note we will use the *358 because it makes the inline multiplies very quick
  22. ; note we divide by 512 so that total difference fits into 32 unsigned bits
  23. ;
  24.  
  25.         EXPORT  map_scaled_rgb_to_palette_index
  26.  
  27.         AREA |ARM$$code|, CODE, READONLY
  28.  
  29.         ROUT
  30.  
  31. str     RN      a1
  32. orig_r  RN      a2
  33. orig_g  RN      a3
  34. orig_b  RN      a4
  35. dmin    RN      v1
  36. i       RN      v2
  37. palette RN      v3
  38. r       RN      v4              ; implicit r < g
  39. g       RN      v5              ; implicit r < g < b
  40. b       RN      v6              ; implicit     g < b
  41. d       RN      ip
  42. t       RN      lr
  43. best    RN      str             ; implicitly a1 as well
  44.  
  45. ;
  46. ; In    R0 -> structure
  47. ;               R0+(3*4) -> array [N][3] of palette intensity [0, 0xffff]
  48. ;               R0+(4*4) = number of colours (N) 
  49. ;       R1 = red nominally [0, 0xffff], but clipped as necessary
  50. ;       R2 = green nominally [0, 0xffff], but clipped as necessary
  51. ;       R3 = blue nominally [0, 0xffff], but clipped as necessary
  52. ; Out   R0 = palette index
  53. ;       structure[0] = error in approximating red intensity
  54. ;       structure[1] = error in approximating green intensity
  55. ;       structure[2] = error in approximating blue intensity
  56. ;
  57. ; the test8bpp program shows this to produce exactly the same result as the
  58. ; floating point algorithm for a single run of 1000 random values
  59. ;
  60.  
  61.         ROUT
  62.  
  63. map_scaled_rgb_to_palette_index
  64.  
  65.         STMFD   sp!, {a1, v1-v6, lr}            ; store a1 as temporary
  66.         MOV     lr, #0xff00
  67.         ORR     lr, lr, #0xff
  68.         CMP     orig_r, #0x10000                ; ensure in range [0, 0xffff]
  69.         MOVHS   orig_r, #0
  70.         MOVGE   orig_r, lr
  71.         CMP     orig_g, #0x10000
  72.         MOVHS   orig_g, #0
  73.         MOVGE   orig_g, lr
  74.         CMP     orig_b, #0x10000
  75.         MOVHS   orig_b, #0
  76.         MOVGE   orig_b, lr
  77.         LDR     palette, [str, #4*3]
  78.         LDR     i, [str, #4*4]
  79.         MOV     dmin, #&ffffffff
  80.         ; for (i= ncolours; (i > 0); i--)
  81. 0
  82.         LDMIA   palette!, {r, g, b}
  83.         SUBS    r, r, orig_r                    ; how different is it?
  84.         RSBMI   r, r, #0                        ; makes multiply faster
  85.         MUL     t, r, r
  86.         ; scale for red   ... |r|^2 * (0.212671 * 358 / 512) = |r|^2 * 0x0.26
  87.         MOV     d, t, LSR #3                    ; |r|^2 * 0x0.20
  88.         ADDNE   d, d, t, LSR #6                 ; |r|^2 * 0x0.24
  89.         ADDNE   d, d, t, LSR #7                 ; |r|^2 * 0x0.26
  90.  
  91.         SUBS    g, g, orig_g
  92.         RSBMI   g, g, #0
  93.         MULNE   t, g, g
  94.         ; scale for green ... |g|^2 * (0.715160 * 358 / 512) = |g|^2 * 0x0.80
  95.         ADDNE   d, d, t, LSR #1                 ; |g|^2 * 0x0.80
  96.  
  97.         SUBS    b, b, orig_b
  98.         RSBMI   b, b, #0
  99.         MULNE   t, b, b
  100.         ; scale for blue  ... |b|^2 * (0.072169 * 358 / 512) = |b|^2 * 0x0.0d
  101.         ADDNE   d, d, t, LSR #5                 ; (|b|^2 / 512) * 0x0.08
  102.         ADDNE   d, d, t, LSR #6                 ; (|b|^2 / 512) * 0x0.0c
  103.         ADDNE   d, d, t, LSR #8                 ; (|b|^2 / 512) * 0x0.0d
  104.  
  105.         ;
  106.         ; if (d < dmin) {
  107.         ;   best = i;
  108.         ;   dmin = d;
  109.         ;   if (dmin == 0) {
  110.         ;     i = 1;
  111.         ;   }
  112.         ; }
  113.         ;
  114.  
  115.         CMP     d, dmin
  116.         MOVLO   best, i                         ; favour earlier entries in table
  117.         MOVLSS  dmin, d                         ; see if zero difference
  118.         MOVEQ   i, #1                           ; yes, abort loop
  119.  
  120.         SUBS    i, i, #1
  121.         BGT     %BT0
  122.  
  123. exact_match
  124.         LDMFD   sp!, {d}                        ; d= pointer to structure
  125.  
  126.         LDR     palette, [d, #3*4]
  127.         LDR     t, [d, #4*4]                    ; t= ncolours
  128.         SUB     best, t, best                   ; best= index into array
  129.  
  130.         ADD     t, best, best, LSL #1
  131.         ADD     palette, palette, t, LSL #2
  132.         LDMIA   palette, {r, g, b}              ; r,g,b= colour that is closest
  133.  
  134.         SUB     r, orig_r, r
  135.         SUB     g, orig_g, g
  136.         SUB     b, orig_b, b
  137.         STMIA   d, {r, g, b}                    ; store error
  138.  
  139.         LDMFD   sp!, {v1-v6, pc}^
  140.  
  141.   END
  142.